package com.wlyuan.index.domain.index.factory;

import com.alibaba.fastjson.JSON;
import com.wlyuan.core.domain.valueobj.CombineId;
import com.wlyuan.index.domain.index.CombineIndex;
import com.wlyuan.index.domain.index.builder.CombineIndexBuilder;
import com.wlyuan.index.domain.index.repository.CombineIndexRepository;
import com.wlyuan.index.domain.source.Source;
import com.wlyuan.index.domain.source.factory.SourceFactory;
import com.wlyuan.index.domain.source.repository.SourceRepository;
import com.wlyuan.index.domain.source.valueobj.SourceId;
import com.wlyuan.lock.annotation.CacheLock;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import lombok.var;
import org.apache.commons.collections4.CollectionUtils;
import org.springframework.stereotype.Service;

@Service
@Slf4j
@RequiredArgsConstructor
public class CombineIndexFactory {
    private final SourceFactory sourceFactory;
    private final CombineIndexRepository indexRepository;
    private final SourceRepository sourceRepository;
    private static final String LOCK_NAME = "PC::LOCK::INDEX::COMBINE_NEW";

    private void addBounds(CombineIndexBuilder builder, Source source) {
        if (CollectionUtils.isEmpty(source.getBoundIds())) {
            return;
        }

        var bounds = sourceRepository.list(source.getBoundIds());
        if (CollectionUtils.isEmpty(bounds)) {
            return;
        }
        builder.withBounds(bounds);
    }

    private void addIndex(CombineIndexBuilder builder, CombineId combineId) {
        var index = indexRepository.ofId(combineId);
        if (null != index) {
            builder.withIndex(index);
        }
    }

    @CacheLock(cacheName = LOCK_NAME, key = "#combineId.id", message = "合单索引锁定失败")
    public CombineIndex create(CombineId combineId) {
        var source = sourceRepository.ofId(new SourceId(combineId));
        if (null == source) {
            source = sourceFactory.create(combineId);
            logger.info("重建合单索引数据: {} {}", combineId, source);
        }

        if (logger.isDebugEnabled()) {
            logger.debug("合单索引数据: {} {}", combineId, source);
        }
        var builder = new CombineIndexBuilder(source);
        this.addIndex(builder, combineId);
        this.addBounds(builder, source);

        // 构建合单索引
        var index = builder.build();
        indexRepository.save(index);

        if (logger.isDebugEnabled()) {
            logger.debug("合单索引更新: {} {}", combineId, JSON.toJSONString(index));
        }
        return index;
    }

    public void remove(CombineId combineId) {
        indexRepository.deleteById(combineId.getId());
    }
}